home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-07-29 | 11.6 KB | 285 lines | [TEXT/sade] |
- # Symbolic Application Debugging Environment 1.3 Final
- #
- # Copyright Apple Computer, Inc. 1987-1991
- # All rights reserved.
-
- ###############################################################################
- # --------------------------------------------------------------------------------------
- # to TRACE THE RESOURCE CHAIN AND DISPLAY RESOURCE MAP INFORMATION
- # select and enter all procs then execute:
- # resmap or resmap "rsrc" to see just info for specified resource type (case sensitive)
- # --------------------------------------------------------------------------------------
-
- proc fileName(FileRefNum)
- define FCBSPTr := $34E
- printf ("File Name: %P ", ^pstring (FCBSPtr^ + fileRefNum + 62)^)
- end
-
-
- proc ResName(nameOffset)
- define resNamePtr
- ResNamePtr := NEXTresFile + (^Word(NEXTresFile + 26)^) # get start of name list
- ResNamePtr := ResNamePtr + nameOffset # add offset into list for this resource.
- printf(" name:%P ", ^pstring(resNamePtr)^)
- end
-
-
- proc ResInfo(refListPtr, numThisType)
- define looper
- define resId
- define resAttributes
- define resHandle
- define resPtr
- define nameOffset
-
- for looper := 0 to numThisType # show info for all resources of current type
- resId := ^Word(refListPtr)^
- printf("\n ID: % 6d", resId) # info for each resource includes: resId
- resHandle := (refListPtr + 8)^
- if resHandle = 0 then # if resource not in memory, say its at 0.
- resPtr := 0
- else
- resPtr := resHandle^ # else give memory location where resource is loaded,
- end
- if $80000000 & resPtr then # note if "locked" bit set in resource's master pointer
- printf " *"
- else
- printf " "
- end
- resPtr := resPtr & $00ffffff
- printf(" at: %.8X", resPtr)
- resAttributes := ^UnsignedByte(refListPtr + 4)^
- printf (" attribs: %.8b", resAttributes) # resource attributes as bit pattern
-
- nameOffset := ^Word(refListPtr+2)^
- if nameOffset <> -1 then # one word offset to resource name from top of name list
- resName(nameOffset) # if no name offset is -1
- end
- refListPtr := refListPtr + 12
- end
- end
-
-
- proc ResTypes (typeListPtr, targetType)
- define numTypes := ^Word(TypeListPtr)^
- define numThisType
- define looper
- define thisResPtr
- define refListPtr
-
- printf (" Number of Resource types: %d\n", numTypes+1) # number of resource types in current map
- for looper := 0 to NumTypes
- ThisResPtr := (typeListPtr + 2) + (looper * 8)
- if targetType = 0 || targetType = thisResPtr^ then # If optional target type spec in call to ResMap
- numThisType := ^Word(thisResPtr + 4)^ # show info only for that type, else show all types
- printf("\n type: %.4s instances: %d", thisResPtr^, numThisType+1)
- refListPtr := ^Word(thisResPtr + 6)^+typeListPtr # find offset into Reference List for type from top of type list.
- ResInfo(refListPtr, numThisType) # get resource info for type.
- end
- end
- end
-
-
-
- proc ResMap targetType
-
- # Global Variables:
- define global NEXTresFile # pointer to top of current resource map
-
- define FileRef
- define typeList
-
- if Nargs = 0 then # if optional target resource type not input, then show info for all types
- targetType := 0 # else show info for target type only
- end
- NEXTresFile := @topMapHndl
- printf "\nRESOURCE CHAIN - Top to bottom:"
- while (NextResFile^ <> 0) # display each resource map in the chain, starting from the top map
-
- NEXTresFile := NEXTresFile^^
-
- IF NEXTresFile = 0
- printf "\nA resource map has been purged--a major problem!\n"
- return
- end
-
- fileRef := ^Word(NEXTresFile+20)^
-
- printf("\n\nResource map at: %.8X File ref num: %X\n", NEXTresFile, fileRef)
- fileName(fileRef) # get file name
- typeList := ^Word(NEXTresFile + 24)^
-
- ResTypes (NEXTresFile + typeList, targetType) # get resource type info
- NextresFile := NextresFile+16;
- end
- printf "\n"
- undefine NEXTresFile # pointer to top of current resource map
-
- end
-
-
- ###############################################################################
-
- func CheckMP (thisBlockHndl,thisZonePtr)
- # function returns a result code of 1 if NotOk and 0 if all is well.
- # verify that the handle is not NIL, and that the master pointer is not odd and is located fully within this zone
- # verify that the master pointer to the block in the resource map matches the
- # master pointer derived from the block's self relative handle
- define selfHndl
- define endZone
- define notOk := 0 # assume all is well
-
- if thisBlockhndl = 0 then # check handle in resource map for valid value
- "\n## block has an invalid NIL handle"
- notOk := 1
- elseif thisBlockHndl^ & $01 = 1 then
- "\n## block has an invalid odd master pointer"
- notOk := 1
- end
- endZone := thisZonePtr^^ & $00ffffff # yields size of zone trailer block
- endZone := thisZonePtr^ + endZone # pointer to zone trailer block plus its length is address of last byte in zone.
- if thisBlockHndl < thisZonePtr || thisBlockHndl + 4 > endZone then
- "\n## block's master pointer falls outside of this zone"
- printf ("zone start %.8x - zone end %.8x - master pointer at %.8x\n",thisZonePtr, endZone, thisBlockHndl)
- notOk := 1
- end
- selfHndl := ((thisBlockHndl^ & $00ffffff )- 8 + 4)^ # yields offset from top ThisZonePtr to this block's master pointer
- selfHndl := thisZonePtr + selfHndl # is location of MP indicated by this block's self-relative handle
- if selfHndl^ <> thisBlockHndl^ then
- "\n## block's self relative handle yields a master pointer which doesn't match the master pointer in the resource map."
- printf("self-relative MP %.8x - resource map MP %.8x (high bytes intact)", selfHndl^, thisBlockHndl^)
- notOk := 1
- end
- return notOk
- end # func CheckMP
-
-
- func BlockInZone(thisBlockHndl, thisZonePtr)
- # function returns a result code of 1 if NotOk and 0 if all is well
- # verify that this block starts in this zone and doesn't extend beyond it
- # also verify that the block size is not 0 or odd
- define endZone
- define blockSize
- define blockStart
- define notOk := 0 # assume will pass all tests
-
- endZone := thisZonePtr^^ & $00ffffff # yields size of zone trailer block
- endZone := thisZoneptr^ + endZone # pointer to zone trailer block plus its length is address of last byte in zone.
- blockSize := ((thisBlockHndl^ & $00ffffff) - 8)^ & $00ffffff #mask MP high byte, backup 8 to block header, mask tag byte
- if blockSize = 0 then # check block size
- "\n## block has an invalid NIL size"
- notOk := 1
- elseif blockSize & $01 = 1 then # (if size is zero it can't also be odd so don't bother to check.)
- "\n## block has an invalid odd size"
- notOk := 1
- end
- blockStart := thisBlockHndl^ & $00ffffff # check block location
- if blockStart < thisZonePtr || blockStart > endZone then
- if thisZonePtr = TheZone then
- "\n## resource map's handle for this block yields a starting address outside of expected location in TheZone"
- elseif thisZonePtr = SysZone
- "\n## resource map's handle for this block yields a starting address outside of expected location in SysZone"
- else
- "\n##resource map's handle for this block yields a starting address outside of TheZone or SysZone"
- end
- printf("start zone %.8x - end zone %.8x - block start %.8x\n", thisZonePtr, endZone, blockStart)
- notOk := 1
- elseif blockStart + blockSize > endZone then
- "\n## block's size extends it beyond the end of this heap zone"
- printf("block start %.8x - block size %.8x - end zone %.8x\n", blockStart, blockSize, endZone)
- notOk := 1
- end
- return notOk
- end # proc BlockInZone
-
-
- func CheckRes (typeListPtr, thisZone)
- # func returns 1 if notOk and 0 if all is well
- # locates master pointer in resMap for all loaded resources, then checks each MP and resource for validity
- # and prints diagnostic information for the resource if a problem is found
-
- define refListPtr, thisResEntry
- define numTypes, numThisType
- define typeLoop, resLoop
- define resZone, resHndl, resPtr
- define resAttributes, resId, nameOffset
- define notOk
-
- numTypes := ^Word (TypeListPtr) ^
- for typeLoop := 0 to NumTypes # for each resource type
- ThisResEntry := typeListPtr + 2 + typeLoop * 8
- numThisType := ^Word(thisResEntry + 4)^ # find how many of this type
- refListPtr := ^Word(thisResEntry + 6)^ # and the start of the reference list for this type
- refListPtr := typeListPtr + refListPtr
- for resLoop := 0 to numThisType
- resHndl := (refListPtr + 8)^
- if resHndl = 0 then
- resPtr := 0
- else
- resPtr := resHndl^ & $00ffffff # get pointer to resource
- end # check only loaded resources
- if resPtr <> 0 then # (a non-zero handle could point to NIL MP if resource was purged)
- resAttributes := refListPtr + 4
- resAttributes := ^Byte (resAttributes)^ # which heap is resource in?
- if resAttributes & $0040 then # if resSysHeap attribute set
- resZone := SysZone # then the resource should be in loaded in the System heap.
- else # else it should be loaded in the current App's heap.
- resZone := TheZone
- end
- notOk := BlockInZone(resHndl,resZone) # master pointer to resource should be in this heap
- notOk := CheckMp(resHndl, thisZone) # where this heap is app heap unless resfile is system's
- if notOk then # an error was reported
- resId := ^Word (refListPtr)^ # give ID and name for the problem resource
- printf("\n ID: % .5d", resId)
- nameOffset := ^Word(refListPtr+2)^
- if nameOffset <> -1 then
- resName(nameOffset)
- end
- end # notOk
- end # resPtr <> 0
- refListPtr := refListPtr + 12 # move on to test next resource in reference list
- end # resLoop # till all resources of this type are tested
- end # typeLoop # then test next resource type
- return notOk
- end # proc CheckRes
-
-
- proc ResVerify
- # verifies all resource maps in the resource chain and all loaded resources (see CheckMP and BlockInZone for details)
- # prints diagnostics if a problem is found
- # reports as an error the case where a resource's attributes indicate it will load in the System heap but
- # the resource is loaded in the application heap anyway because the System heap doesn't have the space
- # (we might want to get fancy at some point and verify that all offsets calculated for tracing the resource map are
- # still within the map, but i figure if we get there the offsets must have been ok.)
-
- # Global Variables:
- define global NEXTresFile # pointer to top of current resource map
-
- define thisZone
- define FileRef
- define typeListOffset
- define nextResHndl := topMapHndl
- define notOk
-
- "\nVerifying the Resource Chain:"
- repeat
- NEXTresFile := nextResHndl^ # (this guy is global - for use in ResName, which is called from CheckRes)
- fileRef := ^Word(NEXTresFile+20)^
- printf("\nResource map at: %.8X File ref num: %X\n", NEXTresFile, fileRef)
- fileName(fileRef)
- if fileRef = 2 then # System resource map and master pointers should be in the System heap
- thisZone := SysZone # all other resource maps and master pointers should be in the current App heap
- else
- thisZone := TheZone
- end
- notOk := CheckMp(nextResHndl, thisZone)
- typeListOffset := ^Word(NEXTresFile + 24)^
- notOk := CheckRes (NEXTresFile + typeListOffset, thisZone)
- if ! notOk then
- "\nlooking good!"
- end
- nextResHndl := (NEXTresFile + 16)^ # check next resource map
- until (nextResHndl = 0) # until no more resource maps to check
- undefine NEXTresFile
- end # proc ResVerify
-